package com.tom.demo.common.utils;

import com.tom.demo.common.entity.SysMenu;
import com.tom.demo.vo.MenuOptionsVo;
import com.tom.demo.vo.MetaVo;
import com.tom.demo.vo.RouterVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 递归菜单
 * 构建路由数据
 */
public class RecursiveMenuUtil {
    /**
     * 将查询到的菜单组成树形菜单
     * @param menuItems
     * @return
     */
    public static List<SysMenu> buildMenuTree(List<SysMenu> menuItems) {
        Map<String, SysMenu> menuItemMap = new HashMap<>();
        List<SysMenu> rootItems = new ArrayList<>();

        // 将所有的菜单项放入map中方便查找
        for (SysMenu item : menuItems) {
            menuItemMap.put(item.getMenuId(), item);
        }
        for (SysMenu item : menuItems) {
            if (item.getParentId().equals("0")) { // 第一级菜单
                rootItems.add(item);
            } else {
                // 如果有父节点，则添加到父节点的children列表中
                SysMenu parentItem = menuItemMap.get(item.getParentId());
                if (parentItem != null) {
                    if (parentItem.getChildren() == null) {
                        parentItem.setChildren(new ArrayList<>());
                    }
                    parentItem.getChildren().add(item);
                }
            }
        }
        return rootItems;
    }


    /**
     * 将树形菜单构建为树形路由
     * @param menus
     * @return
     */
    public static List<RouterVo> buildRouter(List<SysMenu> menus) {
        //创建list集合，存储最终数据
        List<RouterVo> routers = new ArrayList<>();
        //menus遍历
        for(SysMenu menu : menus) {
            RouterVo router = new RouterVo();
            router.setHidden(menu.getVisible());
            router.setAlwaysShow(false);
            router.setPath(getRouterPath(menu));
            //构建parentId=0,但是menuType=C,也就是一级就是菜单，不是目录的情况
            if("0".equals(menu.getParentId())  && "C".equals(menu.getMenuType())){
                router.setComponent("Layout");
                List<RouterVo> routerVos = new ArrayList<>();
                RouterVo routervo = new RouterVo();
                setRouterName(menu, routervo);
                routervo.setPath("index");
                routerVos.add(routervo);
                router.setChildren(routerVos);
                routers.add(router);
                continue;
            }else{
                setRouterName(menu, router);
            }
            //下一层数据部分
            List<SysMenu> children = menu.getChildren();
            //判断是否是菜单
            if("C".equals(menu.getMenuType())) {
                if(!CollectionUtils.isEmpty(children)) {
                    //加载出来下面隐藏路由
                    List<SysMenu> hiddenMenuList = children.stream()
                            .filter(item -> !StringUtils.isEmpty(item.getComponent()))
                            .collect(Collectors.toList());
                    for(SysMenu hiddenMenu : hiddenMenuList) {
                        RouterVo hiddenRouter = new RouterVo();
                        //true 隐藏路由
                        hiddenRouter.setHidden(hiddenMenu.getVisible());
                        hiddenRouter.setAlwaysShow(false);
                        hiddenRouter.setPath(getRouterPath(hiddenMenu));
                        hiddenRouter.setComponent(hiddenMenu.getComponent());
                        hiddenRouter.setMeta(new MetaVo(hiddenMenu.getMenuName(), hiddenMenu.getIcon()));
                        if(!StringUtils.isEmpty(hiddenMenu.getPath())){
                            String path = hiddenMenu.getPath();
                            String  name = path.substring(0, 1).toUpperCase() + path.substring(1);
                            hiddenRouter.setName(name);
                        }
                        routers.add(hiddenRouter);
                    }
                }
            } else {
                if(!CollectionUtils.isEmpty(children)) {
                    router.setAlwaysShow(true);
                    //递归
                    router.setChildren(buildRouter(children));
                }
            }
            routers.add(router);
        }
        return routers;
    }

    private static void setRouterName(SysMenu menu, RouterVo router) {
        if(!StringUtils.isEmpty(menu.getPath())){
            String path = menu.getPath();
            String  name = path.substring(0, 1).toUpperCase() + path.substring(1);
            router.setName(name);
        }
        router.setComponent(menu.getComponent());
        router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
    }

    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    private static String getRouterPath(SysMenu menu) {
        String routerPath = "/" + menu.getPath();
        if(!menu.getParentId().equals("0")) {
            routerPath = menu.getPath();
        }
        return routerPath;
    }


    /**
     * 将查询到的菜单组成树形菜单
     * @param menuItems
     * @return
     */
    public static MenuOptionsVo buildMenuOptions(List<SysMenu> menuItems) {
        List<MenuOptionsVo> menuOptionsVos = convertToMenuOptionsVo(menuItems);
        //创建一次固定的目录
        MenuOptionsVo menuOptionsVo = new MenuOptionsVo();
        menuOptionsVo.setMenuId("0");
        menuOptionsVo.setMenuName("一级类目");
        menuOptionsVo.setChildren(menuOptionsVos);
        return menuOptionsVo;
    }

    /**
     * 根据获取到menu_type构建一个新的菜单树对象
     * @param menuItems
     * @return
     */
    public static List<MenuOptionsVo> convertToMenuOptionsVo(List<SysMenu> menuItems) {
        // 创建一个Map来存放所有菜单项，方便查找
        Map<String, MenuOptionsVo> voMap = new HashMap<>();

        // 首先创建所有的MenuOptionsVo对象并放入map中
        for (SysMenu menu : menuItems) {
            MenuOptionsVo vo = new MenuOptionsVo();
            vo.setMenuId(menu.getMenuId());
            vo.setMenuName(menu.getMenuName());
            vo.setChildren(new ArrayList<>()); // 初始化children列表
            voMap.put(menu.getMenuId(), vo);
        }
        // 构建树状结构
        List<MenuOptionsVo> roots = new ArrayList<>();
        for (SysMenu menu : menuItems) {
            MenuOptionsVo vo = voMap.get(menu.getMenuId());
            if ("0".equals(menu.getParentId())) {
                // 如果是根节点，则直接加入到roots列表中
                roots.add(vo);
            } else {
                // 否则找到父节点，并将其添加到父节点的children列表中
                MenuOptionsVo parentVo = voMap.get(menu.getParentId());
                if (parentVo != null) {
                    parentVo.getChildren().add(vo);
                }
            }
        }
        return roots;
    }
}